from typing import Any

from aiogram import Bot, types
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Back, Button, Cancel, ScrollingGroup, Select
from aiogram_dialog.widgets.text import Const, Format
from apscheduler.schedulers.asyncio import AsyncIOScheduler

from app.bot.dialog.dialog_states import ChangeProxySG
from app.bot.dialog.getters.orders import all_orders_getter
from app.bot.dialog.getters.proxies import (
    available_proxies_for_replace_getter,
    order_proxies_getter,
)
from app.bot.dialog.widgets import LocaleText
from app.bot.services.locale import Locale
from app.bot.services.loggers import logger
from app.bot.services.scheduler import jobs
from app.config import Settings


async def set_order_id(
    call: types.CallbackQuery, widget: Any, manager: DialogManager, order_id: str
):
    manager.dialog_data["order_id"] = order_id
    await manager.switch_to(ChangeProxySG.proxies_list)


async def set_proxy_id(
    call: types.CallbackQuery, widget: Any, manager: DialogManager, proxy_id: str
):

    manager.dialog_data["proxy_id"] = proxy_id
    await manager.switch_to(ChangeProxySG.select_proxy)


async def set_new_proxy_id(
    call: types.CallbackQuery, widget: Any, manager: DialogManager, new_proxy_id: str
):

    manager.dialog_data["new_proxy_id"] = new_proxy_id
    await manager.switch_to(ChangeProxySG.confirm)


async def confirm_changes(
    call: types.CallbackQuery, widget: Any, manager: DialogManager
):
    session_factory = manager.middleware_data.get("session_factory")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")
    scheduler: AsyncIOScheduler = manager.middleware_data.get("scheduler")
    locale: Locale = manager.middleware_data.get("locale")
    order_id: int = manager.dialog_data.get("order_id")
    proxy_id: int = manager.dialog_data.get("proxy_id")
    new_proxy_id: int = manager.dialog_data.get("new_proxy_id")
    user_id = call.from_user.id

    try:
        scheduler.add_job(
            jobs.change_proxy,
            args=(
                bot,
                locale,
                session_factory,
                user_id,
                order_id,
                proxy_id,
                new_proxy_id,
                config,
            ),
        )

        logger.info(f"Добавлена задача по смене прокси в заказе №{order_id}")

        scheduler.add_job(
            jobs.check_proxy_speed_job,
            args=(
                bot,
                locale,
                session_factory,
                user_id,
                new_proxy_id,
                config,
            ),
        )
        logger.info(f"Добавлена задача по проверке скорости прокси №{new_proxy_id}")

        await call.message.answer(locale.get("in-work-msg"))
    except Exception as e:
        logger.exception(e)
        await call.message.answer(locale.get("error-msg"))
    await manager.done()


select_order_window = Window(
    Const("Выберите заказ"),
    ScrollingGroup(
        Select(
            Format("Order №{item.id} {item.summ}$"),
            "ordersel",
            lambda order: order.id,
            "orders",
            on_click=set_order_id,
        ),
        width=2,
        height=4,
        id="orderselect",
    ),
    Cancel(LocaleText("back-btn")),
    state=ChangeProxySG.orders_list,
    getter=all_orders_getter,
)

select_proxy_window = Window(
    Const("Какой прокси заменить?"),
    ScrollingGroup(
        Select(
            Format("{item.login}:{item.password}:{item.port_https}"),
            "proxiessel",
            lambda proxy: proxy.id,
            "proxies",
            on_click=set_proxy_id,
        ),
        width=2,
        height=4,
        id="proxysel",
    ),
    Back(LocaleText("back-btn")),
    state=ChangeProxySG.proxies_list,
    getter=order_proxies_getter,
)


select_new_sproxy_window = Window(
    Const("Выберите новый прокси"),
    ScrollingGroup(
        Select(
            Format("Proxy №{item.id} {item.login}:{item.password}:{item.port_https}"),
            "proxiessel",
            lambda proxy: proxy.id,
            "available_proxies",
            on_click=set_new_proxy_id,
        ),
        width=1,
        height=5,
        id="proxysel",
    ),
    Back(LocaleText("back-btn")),
    state=ChangeProxySG.select_proxy,
    getter=available_proxies_for_replace_getter,
)


confirm_window = Window(
    Const("Подтвердить изменение?"),
    Button(Const("Да"), id="yes", on_click=confirm_changes),
    Button(Const("Нет"), id="no", on_click=confirm_changes),
    Back(LocaleText("back-btn")),
    state=ChangeProxySG.confirm,
)

change_proxy_dialog = Dialog(
    select_order_window,
    select_proxy_window,
    select_new_sproxy_window,
    confirm_window,
)
